/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package utilitarios;

import geradorImagens.CriarBmp;
import imagemBmp.FormatoBmp;
import imagemYUV.novoFormato;
import java.io.IOException;

/**
 *
 * @author jeferson
 */

/*
 * Essa classe contém todos os metedos utilizados para converter de byte para
 * inteiro, de inteiro para byte e de byte em unsigner byte
 */
public class Conversoes {

    public static novoFormato rgb2yuv(FormatoBmp bmp) throws IOException {
        novoFormato auxnovoformato = new novoFormato();
        //seto que ele eh YUV caso o campo isYUV seja um (em byte) o arquivo esta em YUV
        auxnovoformato.isYUV = 1;
        int largura = bmp.getBiWidth();
        int altura = bmp.getBiHeight();
        int tamanho = (largura * 3) * altura;
        int deslocamento = 0;

        if (largura % 4 == 0) {
            deslocamento = 4 - ((largura * 3) % 4);
        }

//        byte[] aux = new byte[bmp.imagem.length - (deslocamento*altura)];
//        
//        //tira o deslocamento
//        int cont = 0, linha = 0;
//        for(int i = 0; i < bmp.imagem.length; i++){           
//            if(linha == ((largura*3)-deslocamento)){
//                i += deslocamento;
//                linha = 0;
//            }
//            aux[cont] = bmp.imagem[i];
//            cont++;
//            linha++;
//        }
        if ((largura % 4) != 0) {
            deslocamento = (4 - ((largura * 3) % 4));
        }
        int linha = 0;
        
        byte[] imagemYUV = new byte[bmp.imagem.length];

        for (int j = 0; j < bmp.imagem.length; j += 3) {
//            if(linha == (largura * 3)){
//                j+=deslocamento;
//                linha = 0;
//            }
            int R = (bmp.imagem[j + 2] & 0xFF);
            int G = (bmp.imagem[j + 1] & 0xFF);
            int B = (bmp.imagem[j] & 0xFF);

            int y = (int) ((0.257 * R) + (0.504 * G) + (0.098 * B) + 16);
            int v = (int) ((0.439 * R) - (0.368 * G) - (0.071 * B) + 128);
            int u = (int) (-(0.148 * R) - (0.291 * G) + (0.439 * B) + 128);

            imagemYUV[j] = (byte) (y);
            imagemYUV[j + 1] = (byte) (u);
            imagemYUV[j + 2] = (byte) (v);
//            linha += 3;
        }

        auxnovoformato.imagem = imagemYUV;
        auxnovoformato.altura = bmp.BiHeight;
        System.out.println("altura rgb2yuv = " + Conversoes.byteArray2Int4(auxnovoformato.altura));
        auxnovoformato.largura = bmp.BiWidth;
        System.out.println("largura rgb2yuv = " + Conversoes.byteArray2Int4(auxnovoformato.largura));
        return auxnovoformato;
    }

    public byte[] vetorSalvar(novoFormato YUV, boolean yuv, boolean poenull) {
        byte[] vetor;

        //caso a imagem seja bmp não houve modificações de formato então mantem o vetor de bytes original
        if (yuv == false) {
            return CriarBmp.imagem;
        } //a transformação yuv foi a aplicada e o vetor de bytes original foi alterado
        else {

            if (YUV.isCompressed == 1) {
                vetor = new byte[10 + YUV.imagemComprimida.length];
                vetor[0] = YUV.isYUV;
                vetor[1] = YUV.isCompressed;
                for (int i = 0; i < 4; i++) {
                    vetor[i + 2] = YUV.altura[i];
                }
                for (int i = 0; i < 4; i++) {
                    vetor[i + 6] = YUV.largura[i];
                }

                for (int i = 0; i < YUV.imagemComprimida.length; i++) {
                    vetor[i + 10] = YUV.imagemComprimida[i];
                }

            } else {
                vetor = new byte[10 + YUV.imagem.length];
                vetor[0] = YUV.isYUV;
                vetor[1] = YUV.isCompressed;
                for (int i = 4; i < YUV.imagem.length; i++) {
                    vetor[i] = YUV.imagem[i - 4];
                }
                System.out.println("tamanho do vetor2 = " + vetor.length);
            }


        }
        if (poenull) {
            System.out.println("entrou poe null");
            YUV.imagem = null;
        }
        return vetor;
    }

    public byte[] vetorSalvar(FormatoBmp bmp, boolean yuv) {
        byte[] vetor = new byte[byteArray2Int4(bmp.BfSize)];

        //caso a imagem seja bmp não houve modificações de formato então mantem o vetor de bytes original
        if (yuv == false) {
            return CriarBmp.imagem;
        } //a transformação yuv foi a aplicada e o vetor de bytes original foi alterado
        else {
            for (int i = 0; i < 54; i++) {
                if (i == 0 || i == 1) {
                    vetor[i] = bmp.BfType[i];
                }
                if (i >= 2 && i <= 5) {
                    vetor[i] = bmp.BfSize[i - 2];
                }
                if (i == 6 || i == 7) {
                    vetor[i] = bmp.BfReser1[i - 6];
                }
                if (i == 8 || i == 9) {
                    vetor[i] = bmp.BfReser2[i - 8];
                }
                if (i >= 10 && i <= 13) {
                    vetor[i] = bmp.BfOffSetBits[i - 10];
                }
                if (i >= 14 && i <= 17) {
                    vetor[i] = bmp.BiSize[i - 14];
                }
                if (i >= 18 && i <= 21) {
                    vetor[i] = bmp.BiWidth[i - 18];
                }
                if (i >= 22 && i <= 25) {
                    vetor[i] = bmp.BiHeight[i - 22];
                }
                if (i == 26 || i == 27) {
                    vetor[i] = bmp.BiPlanes[i - 26];
                }
                if (i == 28 || i == 29) {
                    vetor[i] = bmp.BiBitCount[i - 28];
                }
                if (i >= 30 && i <= 33) {
                    vetor[i] = bmp.BiCompress[i - 30];
                }
                if (i >= 34 && i <= 37) {
                    vetor[i] = bmp.BiSizeImag[i - 34];
                }
                if (i >= 38 && i <= 41) {
                    vetor[i] = bmp.BiXPPMeter[i - 38];
                }
                if (i >= 42 && i <= 45) {
                    vetor[i] = bmp.BiYPPMeter[i - 42];
                }
                if (i >= 46 && i <= 49) {
                    vetor[i] = bmp.BiClrUsed[i - 46];
                }
                if (i >= 50 && i <= 53) {
                    vetor[i] = bmp.BiClrImpor[i - 50];
                }
            }

            short tamanho = Conversoes.byteArray2Short(bmp.BiBitCount);
            if (tamanho <= 8) {
                for (int i = 54; i < bmp.paleta.length; i++) {
                    vetor[i] = (byte) bmp.paleta[i - 54].getR();
                    vetor[i] = (byte) bmp.paleta[i - 54].getG();
                    vetor[i] = (byte) bmp.paleta[i - 54].getB();
                    vetor[i] = (byte) bmp.paleta[i - 54].getA();
                }
                int deslocamento = 54 + bmp.paleta.length;
                for (int i = deslocamento; i < bmp.imagem.length; i++) {
                    vetor[i] = bmp.imagem[i - deslocamento];
                }
            } else {
                for (int i = 54; i < bmp.imagem.length; i++) {
                    vetor[i] = bmp.imagem[i - 54];
                }
            }
        }
        return vetor;
    }

    public static int byteArray2Int4(byte[] b) {
        return (b[3] << 24)
                + ((b[2] & 0xFF) << 16)
                + ((b[1] & 0xFF) << 8)
                + (b[0] & 0xFF);
    }

    public static int byteArray2Int2(byte[] b) {
        return ((b[1] & 0xFF) << 2)
                + (b[0] & 0xFF);
    }

    @SuppressWarnings("ShiftOutOfRange")
    public static long byteArray2long(byte[] b) {
        return (b[0] << 56)
                + ((b[1] & 0xFF) << 48)
                + ((b[2] & 0xFF) << 40)
                + ((b[3] & 0xFF) << 32)
                + ((b[4] & 0xFF) << 24)
                + ((b[5] & 0xFF) << 16)
                + ((b[6] & 0xFF) << 8)
                + (b[7] & 0xFF);
    }

    public static short byteArray2Short(byte[] b) {
        return (short) ((b[1] << 2)
                + (b[0] & 0xFF));
    }

    public static byte unsignerByte(byte b) {
        return (byte) (b + 128);
    }

    public static byte[] intToByteArray(int value) {
        byte[] b = new byte[4];
        for (int i = 0; i < 4; i++) {
            int offset = (b.length - 1 - i) * 8;
            b[i] = (byte) ((value >>> offset) & 0xFF);
        }
        return b;
    }

    public static byte[] toBytes(int i) {
        byte[] result = new byte[4];

        result[0] = (byte) (i);
        result[1] = 0;


        return result;
    }
}
